package org.noote.libs.camera.broadcast;

import java.util.Locale;

import org.noote.libs.graphicbuffer.GraphicBuffer;
import org.noote.libs.graphicbuffer.GraphicView;
import org.noote.libs.tcpip.IPClient;
import org.noote.libs.tcpip.IPClient_ConnectedThread;
import org.noote.libs.tcpip.IPEvent_Client;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.Base64;
import android.util.Log;

public class CameraClient extends GraphicView {
	static final String TAG = "CameraClient";

	public interface onEventListener {
		public void onConnected();
		public void onDisconnected();
		public void onError(String sMessage);
		public void onGrabbedFrame(GraphicBuffer frame);
	}

	private class IPEvents implements IPEvent_Client {
		static final String TAG = "CameraClient.IPEvents";
		
		@SuppressWarnings("unused")
		IPClient_ConnectedThread _thread = null; // future use :)
		private boolean _isDebug = false;

		@Override
		public void setThread(IPClient_ConnectedThread thread)
		{
			_thread = thread;
		}
		
		@Override
		public void onConnected() {
			if(_listener != null)
				_listener.onConnected();       		
		}
		
		@Override
		public void onDisconnected() {
			if(_listener != null)
				_listener.onDisconnected();       		
		}
		
		@Override
		public void onError(String sError) {
       		Log.e(TAG, sError);
			if(_listener != null)
				_listener.onError(sError);       		
		}
		
		@Override
		public void onText(String sText) {
		}
		
		@Override
		public void onCmd(String sCmd) {
        	if(_isDebug)
        		Log.d(TAG, "Get cmd : "+sCmd);
    		String [] sCmds = sCmd.split("\\:");
    		if(sCmds.length==2)
    		{
    			String sOrder = sCmds[0].trim().toLowerCase(Locale.getDefault());
    			String sOps = sCmds[1].trim();
    			if(sOrder.equalsIgnoreCase("jpg_preview"))
    			{
    				// get image and decode !
    				decompressJpgPreview(sOps);
    			}
    		}
		}

		private synchronized void decompressJpgPreview(String sOps) {
			String sJpg="";
			int iRatio=30;
			
			// parse datas
			String [] sValues = sOps.split("\\,");
			for(String sValue : sValues)
			{
				String [] sDatas = sValue.split("\\=");
				if(sDatas.length==2)
				{
	    			String sOrder = sDatas[0].trim().toLowerCase(Locale.getDefault());
	    			String sOp = sDatas[1].trim();

					if(sOrder.equalsIgnoreCase("ratio"))
						iRatio = Integer.parseInt(sOp);
					else if(sOrder.equalsIgnoreCase("data"))
						sJpg = sOp;
				}
			}
			if(sJpg.length()==0)
			{
				Log.e(TAG, "Invalid JPG base64 data");
				if(_listener != null)
					_listener.onError("JPG : Invalid base64 data");
				return;
			}
			if(iRatio<0 || iRatio>100)
			{
				Log.e(TAG, "Invalid JPG compression ratio");
				if(_listener != null)
					_listener.onError("JPG : Invalid compression ratio");
				return;
			}
			
			// decode base64 JPG
			byte [] jpg = Base64.decode(sJpg, Base64.NO_WRAP|Base64.NO_PADDING|Base64.URL_SAFE);
			if(jpg == null)
			{
				Log.e(TAG, "Invalid JPG byte data");
				if(_listener != null)
					_listener.onError("JPG : Invalid byte data");
				return;
			}
			
			// decode JPG to Bitmap
			Bitmap bitmapJpg = BitmapFactory.decodeByteArray(jpg, 0, jpg.length);
			if(bitmapJpg == null)
			{
				Log.e(TAG, "Cannot decode JPG byte data");
				if(_listener != null)
					_listener.onError("JPG : Cannot decode data");
				return;
			}
			
			// push Bitmap in GraphicBuffer in right format ARGB8888
			push(bitmapJpg);
			bitmapJpg.recycle();
			
			// Push event :)
			if(_listener != null)
				_listener.onGrabbedFrame(_buffer);
		}
	}

	private IPEvents _events;
	private IPClient _client;
	private onEventListener _listener = null;

	public CameraClient(Context context) {
		super(context);
		
		_events = new IPEvents();
		_client = new IPClient(_events);
	}

	public synchronized boolean connect(String sServerIP, int iPort)
	{
		if(isConnected())
		{
			Log.d(TAG, "Already connected");
			return true;
		}
		
		return _client.connect(sServerIP, iPort);
	}
	

	public synchronized boolean disconnect()
	{
		if(!isConnected())
		{
			Log.d(TAG, "Already disconnected");
			return true;
		}
		
		_client.sendCommand("disconnect", "");
		
		return _client.close();
	}
	
	public boolean isConnected()
	{
		return _client.isConnected();
	}

	public synchronized void askJpegPreview(int iRatio)
	{
		_client.sendCommand("jpg_preview", "ratio="+iRatio);
	}
	
	public synchronized void setOnEventListener(onEventListener listener)
	{
		this._listener = listener;
	}
}
